/*
 * This class is used to serve as a source for SQL; we do our best not to include SQL in our source
 * code; we will keep the SQL in an XML file so that its easily editable; the aim is to limit the need to
 * have to recompile, rebuild, and redeploy our system modules by loading the SQL from an XML file
 * and storing the strings in memory for access by our application
 */

package java113.dataAccess;

//include xml packages
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
import java.util.*;
import java.io.*;

public class DAOBase extends DefaultHandler
{
    
    /** Creates a new instance of DAOBase */
    public DAOBase ()
    {
    }



    //used to hold the current contents of the xml that is being parsed
    private CharArrayWriter m_oContents;

    //will be used to contain the information for the current table of sql queries as the XML is parsed
    private Hashtable m_hSQLTable;
    


    /**
     * Used to initialize the class and parse the XML
     *
     *  @param String strInXMLPath      full path to the XML
     */
    public void load(String strInXMLPath, String runningAsWebApp) throws Exception
    {
    	InputStream oInputStream;

        //the following 5 lines of code are canned; they typically not change
        this.m_oContents = new CharArrayWriter();  //create a bucket for the current contents of the XML
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        ParserAdapter pa = new ParserAdapter(sp.getParser());
        pa.setContentHandler(this);

        //derive a stream from the file and parse
        this.m_hSQLTable = new Hashtable();

        if (runningAsWebApp.equalsIgnoreCase("true")) {

            oInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(strInXMLPath);

        } else {

            oInputStream = new FileInputStream(strInXMLPath);

        }

        

        

        pa.parse(new InputSource(oInputStream));  //parse() will parse the stream represented by the file in strInXMLPath
    }

    
    /**
     * This method is used to determine the start point of an element in an
     * XML stream as it is being parsed; method is called when the parser has identified the beginning of
     * an element; hence, it is called for each and every beginning element found in the XML
     *
     * @param String localName      the name of the element
     * @param Attributes attr               a map-like structure that contains all element attributes
     */
    public void startElement(String namespaceURI, String localName, String qName, Attributes attr) throws SAXException
    {
        this.m_oContents.reset();  //used to capture the current textual information for an element

        //here, we are checking the name of the elements that we are expecting to encounter in the XML; if an 
        //element is encountered, then we will handle it; in our case, we will create an object instance and store it
        //since we will be using it; only elements that are currently being acted on are of interest; nested elements
        //could have multiple instances instantiated; we will discuss this more in class; if we encounter an element
        //that we did not account for, then the data is lost as we will not do anything with it
        if(localName.equalsIgnoreCase("SQLENTRY"))
        {
            String strName, strValue;
            
            strName = attr.getValue("NAME");
            strValue = attr.getValue("VALUE");
            
            if((strName == null || strName.trim ().length () == 0) ||
                    (strValue == null || strValue.trim ().length () == 0))  //defensive coding
                return;
            else
            {
                this.m_hSQLTable.put (strName, strValue);
            }
        }
    }

    /**
     * Override methods of the DefaultHandler class to gain notification of SAX Events. See
     * org.xml.sax.ContentHandler for all available events
     *
     * This method is used to retrieve the characters in the XML stream
     */
    public void characters(char[] ch, int start, int length) throws SAXException
    {
        this.m_oContents.write(ch, start, length);
    }

    /**
     * Get an SQL string given a name
     *
     * @param String strInName
     */
    public String getSQL(String strInName) throws Exception
    {
        if(this.m_hSQLTable != null)  //defensive coding
            return (String) this.m_hSQLTable.get (strInName);
        else
            throw new Exception("The SQL table must first be loaded.");
    }
}
